package com.github.icloudpay.pay.core.service.refund;

import java.math.BigDecimal;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.icloudpay.pay.core.biz.PayOrderBiz;
import com.github.icloudpay.pay.core.biz.PaySerialBiz;
import com.github.icloudpay.pay.core.biz.RefundOrderBiz;
import com.github.icloudpay.pay.core.biz.RefundSerialBiz;
import com.github.icloudpay.pay.core.entity.PayChannelInterface;
import com.github.icloudpay.pay.core.entity.PayOrder;
import com.github.icloudpay.pay.core.entity.PaySerial;
import com.github.icloudpay.pay.core.entity.RefundOrder;
import com.github.icloudpay.pay.core.entity.RefundSerial;
import com.github.icloudpay.pay.core.inter.RefundHandlerService;
import com.github.icloudpay.pay.core.inter.RefundService;
import com.github.icloudpay.pay.core.mapper.PayChannelInterfaceMapper;
import com.github.icloudpay.pay.core.util.SpringContextHolder;
import com.github.wxiaoqi.security.common.admin.pay.request.RefundApplyRequest;
import com.github.wxiaoqi.security.common.admin.pay.request.RefundRequest;
import com.github.wxiaoqi.security.common.admin.pay.response.RefundApplyResponse;
import com.github.wxiaoqi.security.common.admin.pay.response.RefundResponse;
import com.github.wxiaoqi.security.common.msg.ResponseCode;
import com.github.wxiaoqi.security.common.util.SequenceUtil;

/** 
 * @author: bolei
 * @date：Jun 14, 2017 7:29:25 AM 
 * @description：退款逻辑接口
 */

@Service("refundHandlerService")
public class RefundHandlerServiceImpl implements RefundHandlerService{

	private static final Logger logger = LoggerFactory.getLogger(RefundHandlerServiceImpl.class);

	@Autowired
	private PayOrderBiz payOrderBiz;
	@Autowired
	private PaySerialBiz paySerialBiz;
	@Autowired
	private PayChannelInterfaceMapper payChannelInterfaceMapper;
	@Autowired
	private RefundSerialBiz refundSerialBiz;
	@Autowired
	private RefundOrderBiz refundOrderBiz;

	/**
	 * 退款申请
	 * 创建退款订单
	 */
	public RefundApplyResponse refundApply(RefundApplyRequest request){

		RefundApplyResponse response = new RefundApplyResponse();
		String amt = request.getRefundAmt();

		//查询支付订单，并校验是否可以退款
		PayOrder payOrder = new PayOrder();
		payOrder.setPayOrderNo(request.getPayOrderNo());
		payOrder.setPlatformId(request.getPlatformId());
		PayOrder selectPayOrder = payOrderBiz.selectOne(payOrder);
		if(selectPayOrder == null){
			response.setSuccess(false);
			response.setCode(ResponseCode.ORDER_NO_EXIST.getCode());
			response.setMsg(ResponseCode.ORDER_NO_EXIST.getMessage());
			return response;
		}
		if(!"00".equals(selectPayOrder.getOrderStatus())){
			response.setSuccess(false);
			response.setCode(ResponseCode.PAY_NOT_SUCCESS_CAN_NOT_REFUND.getCode());
			response.setMsg(ResponseCode.PAY_NOT_SUCCESS_CAN_NOT_REFUND.getMessage());
			return response;
		}
		
		//金额校验
		BigDecimal refundedAmt = selectPayOrder.getRefundedAmt();//已退款金额
		BigDecimal payAmt = selectPayOrder.getPayAmt();//总付金额
		BigDecimal refundAmt = new BigDecimal(amt);//退款金额
		if(refundedAmt.add(refundAmt).compareTo(payAmt) > 0){
			response.setSuccess(false);
			response.setCode(ResponseCode.REFUND_AMT_OVER_LIMIT.getCode());
			response.setMsg(ResponseCode.REFUND_AMT_OVER_LIMIT.getMessage());
			return response;
		}

		PaySerial paySerial = new PaySerial();
		paySerial.setPayOrderNo(request.getPayOrderNo());
		paySerial.setPlatformId(request.getPlatformId());
		paySerial.setPayStatus("00");//支付成功
		PaySerial selectPaySerial = paySerialBiz.selectOne(paySerial);
		if(selectPaySerial == null){
			response.setSuccess(false);
			response.setCode(ResponseCode.PAY_SERIAL_NOTEXIST.getCode());
			response.setMsg(ResponseCode.PAY_SERIAL_NOTEXIST.getMessage());
			return response;
		}
		RefundOrder refundOrder = new RefundOrder();
		refundOrder.setPlatformId(request.getPlatformId());
		refundOrder.setRefundOrderNo(request.getRefundOrderNo());
		RefundOrder selectRefundOrder = refundOrderBiz.selectOne(refundOrder);
		if(selectRefundOrder != null){
			response.setSuccess(false);
			response.setCode(ResponseCode.ORDER_REFUND.getCode());
			response.setMsg(ResponseCode.ORDER_REFUND.getMessage());
			return response;
		}
		//创建退款订单
		RefundOrder insertOrder = createRefundOrder(request, selectPayOrder);
		refundOrderBiz.insert(insertOrder);
		response.setRefundOrderNo(request.getRefundOrderNo());
        response.setSuccess(true);
		response.setCode(ResponseCode.OK.getCode());
		response.setMsg(ResponseCode.OK.getMessage());
		return response;
	}

	/**
	 * 退款审核
	 * 创建退款流水
	 */
	public RefundResponse refund(RefundRequest request) {

		RefundResponse response = new RefundResponse();
		
		//订单校验
		RefundOrder refundOrder = new RefundOrder();
		refundOrder.setPlatformId(request.getPlatformId());
		refundOrder.setRefundOrderNo(request.getRefundOrderNo());
		refundOrder.setRefundStatus("03");//退款已发起
		RefundOrder selectRefundOrder = refundOrderBiz.selectOne(refundOrder);
		if(selectRefundOrder == null){
			response.setSuccess(false);
			response.setCode(ResponseCode.ORDER_NO_EXIST.getCode());
			response.setMsg(ResponseCode.ORDER_NO_EXIST.getMessage());
			return response;
		}
		
		PayOrder payOrder = new PayOrder();
		payOrder.setPayOrderNo(selectRefundOrder.getPayOrderNo());
		payOrder.setPlatformId(request.getPlatformId());
		PayOrder selectPayOrder = payOrderBiz.selectOne(payOrder);
		if(selectPayOrder == null){
			response.setSuccess(false);
			response.setCode(ResponseCode.ORDER_NO_EXIST.getCode());
			response.setMsg(ResponseCode.ORDER_NO_EXIST.getMessage());
			return response;
		}
		
		PaySerial paySerial = new PaySerial();
		paySerial.setPayOrderNo(selectRefundOrder.getPayOrderNo());
		paySerial.setPlatformId(request.getPlatformId());
		paySerial.setPayStatus("00");//支付成功
		PaySerial selectPaySerial = paySerialBiz.selectOne(paySerial);
		if(selectPaySerial == null){
			response.setSuccess(false);
			response.setCode(ResponseCode.PAY_SERIAL_NOTEXIST.getCode());
			response.setMsg(ResponseCode.PAY_SERIAL_NOTEXIST.getMessage());
			return response;
		}

		//根据支付通道查询退款方法
		PayChannelInterface payChannelInterface = new PayChannelInterface();
		payChannelInterface.setPayChannelNo(selectPaySerial.getPayChannelNo());
		payChannelInterface.setTradeType("02");//退款
		PayChannelInterface selectInterface = payChannelInterfaceMapper.selectOne(payChannelInterface);
		if(null == selectInterface || null == selectInterface.getServiceName()){
			logger.error("查询支付通道接口为null,支付通道编号:{}", selectPaySerial.getPayChannelNo());
			response.setSuccess(false);
			response.setCode(ResponseCode.INTERFACE_NOTEXIST.getCode());
			response.setMsg(ResponseCode.INTERFACE_NOTEXIST.getMessage());
			return response;
		}
		RefundService refundService = SpringContextHolder.getBean(selectInterface.getServiceName());
		
		//创建退款流水
		RefundSerial insertSerial = createRefundSerial(request, selectPaySerial, selectRefundOrder);
		refundSerialBiz.insert(insertSerial);

		request.setPayChannelNo(selectPaySerial.getPayChannelNo());
		request.setPayCompanyNo(selectPaySerial.getPayCompanyNo());
		request.setMerchantId(selectPayOrder.getMerchantId());
		request.setOrdAmt(String.valueOf(selectPayOrder.getPayAmt()));
		request.setSerialNo(selectPaySerial.getSerialNo());
		request.setRefundAmt(String.valueOf(selectRefundOrder.getRefundAmt()));
		request.setRefundSerialNo(insertSerial.getSerialNo());
		RefundResponse refundResponse = refundService.refundNoPwd(request);
		if(ResponseCode.OK.getCode().equals(refundResponse.getCode())){
			//成功,更新订单流水状态
			selectRefundOrder.setRefundStatus("02");//退款处理中
			refundOrderBiz.updateById(selectRefundOrder);
			RefundSerial newRefundSerial = new RefundSerial();
			newRefundSerial.setSerialNo(insertSerial.getSerialNo());
			RefundSerial selectRefundSerial = refundSerialBiz.selectOne(newRefundSerial);
			selectRefundSerial.setRefundStatus("02");//退款处理中
			refundSerialBiz.updateById(selectRefundSerial);
		}
		return refundResponse;
	}

	/**
	 * 组装退款订单参数
	 * @param request
	 * @param selectPayOrder
	 * @return
	 */
	private RefundOrder createRefundOrder(RefundApplyRequest request, PayOrder selectPayOrder){
		RefundOrder refundOrder = new RefundOrder();
		refundOrder.setPayOrderNo(request.getPayOrderNo());
		refundOrder.setPlatformId(request.getPlatformId());
		refundOrder.setMerchantId(selectPayOrder.getMerchantId());
		refundOrder.setRefundAmt(new BigDecimal(request.getRefundAmt()));
		refundOrder.setRefundMethod(selectPayOrder.getPayMethod());
		refundOrder.setRefundOrderNo(request.getRefundOrderNo());
		refundOrder.setRefundReason(request.getRefundReason());
		refundOrder.setRefundStatus("03");//退款已发起
		refundOrder.setRefundTime(new Date());
		return refundOrder;
	}

	/**
	 * 组装退款流水参数
	 * @param request
	 * @param selectPaySerial
	 * @param selectRefundOrder
	 * @return
	 */
	private RefundSerial createRefundSerial(RefundRequest request, PaySerial selectPaySerial, RefundOrder selectRefundOrder){
		RefundSerial refundSerial = new RefundSerial();
		refundSerial.setPayChannelNo(selectPaySerial.getPayChannelNo());
		refundSerial.setPayCompanyNo(selectPaySerial.getPayCompanyNo());
		refundSerial.setPlatformId(request.getPlatformId());
		refundSerial.setMerchantId(selectRefundOrder.getMerchantId());
		refundSerial.setRefundOrderNo(request.getRefundOrderNo());
		refundSerial.setRefundAmt(selectRefundOrder.getRefundAmt());
		refundSerial.setRefundFee(selectRefundOrder.getRefundFee());
		refundSerial.setSerialNo(SequenceUtil.Create27DigitalOrAlphabet());
		refundSerial.setRefundStatus("03");//退款已发起
		return refundSerial;
	}

}
